home *** CD-ROM | disk | FTP | other *** search
- /*
- * rc.c -- routines for processing the configuration file
- *
- * AUTHOR: Savio Lam (lam836@cs.cuhk.hk)
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include "dialog.h"
-
- #ifdef HAVE_NCURSES
- #include "colors.h"
- /*
- * For matching color names with color values
- */
- color_names_st color_names[] =
- {
- {"BLACK", COLOR_BLACK},
- {"RED", COLOR_RED},
- {"GREEN", COLOR_GREEN},
- {"YELLOW", COLOR_YELLOW},
- {"BLUE", COLOR_BLUE},
- {"MAGENTA", COLOR_MAGENTA},
- {"CYAN", COLOR_CYAN},
- {"WHITE", COLOR_WHITE},
- }; /* color names */
- #endif
-
- #define DIALOGRC ".dialogrc"
- #define VAR_LEN 30
- #define COMMENT_LEN 70
-
- /* Types of values */
- #define VAL_INT 0
- #define VAL_STR 1
- #define VAL_BOOL 2
- #define VAL_ATTR 3
-
- /* Type of line in configuration file */
- #define LINE_BLANK 2
- #define LINE_COMMENT 1
- #define LINE_OK 0
- #define LINE_ERROR -1
-
- /* number of configuration variables */
- #define VAR_COUNT (sizeof(vars) / sizeof(vars_st))
-
- /* check if character is white space */
- #define whitespace(c) (c == ' ' || c == '\t')
-
- /* check if character is string quoting characters */
- #define isquote(c) (c == '"' || c == '\'')
-
- /* get last character of string */
- #define lastch(str) str[strlen(str)-1]
-
- /*
- * Configuration variables
- */
- typedef struct {
- char name[VAR_LEN]; /* name of configuration variable as in DIALOGRC */
- void *var; /* address of actually variable to change */
- int type; /* type of value */
- char comment[COMMENT_LEN]; /* comment to put in "rc" file */
- } vars_st;
-
- vars_st vars[] =
- {
- {"use_shadow",
- &use_shadow,
- VAL_BOOL,
- "Shadow dialog boxes? This also turns on color."},
-
- {"use_colors",
- &use_colors,
- VAL_BOOL,
- "Turn color support ON or OFF"},
-
- {"screen_color",
- color_table[0],
- VAL_ATTR,
- "Screen color"},
-
- {"shadow_color",
- color_table[1],
- VAL_ATTR,
- "Shadow color"},
-
- {"dialog_color",
- color_table[2],
- VAL_ATTR,
- "Dialog box color"},
-
- {"title_color",
- color_table[3],
- VAL_ATTR,
- "Dialog box title color"},
-
- {"border_color",
- color_table[4],
- VAL_ATTR,
- "Dialog box border color"},
-
- {"button_active_color",
- color_table[5],
- VAL_ATTR,
- "Active button color"},
-
- {"button_inactive_color",
- color_table[6],
- VAL_ATTR,
- "Inactive button color"},
-
- {"button_key_active_color",
- color_table[7],
- VAL_ATTR,
- "Active button key color"},
-
- {"button_key_inactive_color",
- color_table[8],
- VAL_ATTR,
- "Inactive button key color"},
-
- {"button_label_active_color",
- color_table[9],
- VAL_ATTR,
- "Active button label color"},
-
- {"button_label_inactive_color",
- color_table[10],
- VAL_ATTR,
- "Inactive button label color"},
-
- {"inputbox_color",
- color_table[11],
- VAL_ATTR,
- "Input box color"},
-
- {"inputbox_border_color",
- color_table[12],
- VAL_ATTR,
- "Input box border color"},
-
- {"searchbox_color",
- color_table[13],
- VAL_ATTR,
- "Search box color"},
-
- {"searchbox_title_color",
- color_table[14],
- VAL_ATTR,
- "Search box title color"},
-
- {"searchbox_border_color",
- color_table[15],
- VAL_ATTR,
- "Search box border color"},
-
- {"position_indicator_color",
- color_table[16],
- VAL_ATTR,
- "File position indicator color"},
-
- {"menubox_color",
- color_table[17],
- VAL_ATTR,
- "Menu box color"},
-
- {"menubox_border_color",
- color_table[18],
- VAL_ATTR,
- "Menu box border color"},
-
- {"item_color",
- color_table[19],
- VAL_ATTR,
- "Item color"},
-
- {"item_selected_color",
- color_table[20],
- VAL_ATTR,
- "Selected item color"},
-
- {"tag_color",
- color_table[21],
- VAL_ATTR,
- "Tag color"},
-
- {"tag_selected_color",
- color_table[22],
- VAL_ATTR,
- "Selected tag color"},
-
- {"tag_key_color",
- color_table[23],
- VAL_ATTR,
- "Tag key color"},
-
- {"tag_key_selected_color",
- color_table[24],
- VAL_ATTR,
- "Selected tag key color"},
-
- {"check_color",
- color_table[25],
- VAL_ATTR,
- "Check box color"},
-
- {"check_selected_color",
- color_table[26],
- VAL_ATTR,
- "Selected check box color"},
-
- {"uarrow_color",
- color_table[27],
- VAL_ATTR,
- "Up arrow color"},
-
- {"darrow_color",
- color_table[28],
- VAL_ATTR,
- "Down arrow color"}
- }; /* vars */
-
- static char *attr_to_str (int fg, int bg, int hl);
- static int str_to_attr (char *str, int *fg, int *bg, int *hl);
- static int parse_line (char *line, char **var, char **value);
-
- /*
- * Create the configuration file
- */
- void
- create_rc (const char *filename)
- {
- int i;
- FILE *rc_file;
-
- if ((rc_file = fopen (filename, "wt")) == NULL) {
- fprintf (stderr, "\nError opening file for writing in create_rc().\n");
- exit (-1);
- }
- fprintf (rc_file, "#\
- \n# Run-time configuration file for dialog\
- \n#\
- \n# Automatically generated by \"dialog --create-rc <file>\"\
- \n#\
- \n#\
- \n# Types of values:\
- \n#\
- \n# Number - <number>\
- \n# String - \"string\"\
- \n# Boolean - <ON|OFF>\
- \n# Attribute - (foreground,background,highlight?)\
- \n#\n\n");
-
- /* Print an entry for each configuration variable */
- for (i = 0; i < VAR_COUNT; i++) {
- fprintf (rc_file, "\n# %s\n", vars[i].comment);
- switch (vars[i].type) {
- case VAL_INT:
- fprintf (rc_file, "%s = %d\n", vars[i].name,
- *((int *) vars[i].var));
- break;
- case VAL_STR:
- fprintf (rc_file, "%s = \"%s\"\n", vars[i].name,
- (char *) vars[i].var);
- break;
- case VAL_BOOL:
- fprintf (rc_file, "%s = %s\n", vars[i].name,
- *((bool *) vars[i].var) ? "ON" : "OFF");
- break;
- case VAL_ATTR:
- fprintf (rc_file, "%s = %s\n", vars[i].name,
- attr_to_str (((int *) vars[i].var)[0],
- ((int *) vars[i].var)[1], ((int *) vars[i].var)[2]));
- break;
- }
- }
-
- fclose (rc_file);
- }
-
-
- /*
- * Parse the configuration file and set up variables
- */
- int
- parse_rc (void)
- {
- int i, l = 1, parse, fg, bg, hl;
- char str[MAX_LEN + 1], *var, *value, *tempptr;
- FILE *rc_file;
-
- /*
-
- * At start, 'dialog' determines the settings to use as follows:
- *
- * a) if environment variable DIALOGRC is set, it's value determines the
- * name of the configuration file.
- *
- * b) if the file in (a) can't be found, use the file $HOME/.dialogrc
- * as the configuration file.
- *
- * c) if the file in (b) can't be found, use compiled in defaults.
- *
- */
-
- if ((tempptr = getenv ("DIALOGRC")) != NULL)
- rc_file = fopen (tempptr, "rt");
-
- if (tempptr == NULL || rc_file == NULL) { /* step (a) failed? */
- /* try step (b) */
- if ((tempptr = getenv ("HOME")) == NULL)
- return 0; /* step (b) failed, use default values */
-
- if (tempptr[0] == '\0' || lastch (tempptr) == '/')
- sprintf (str, "%s%s", tempptr, DIALOGRC);
- else
- sprintf (str, "%s/%s", tempptr, DIALOGRC);
-
- if ((rc_file = fopen (str, "rt")) == NULL)
- return 0; /* step (b) failed, use default values */
- }
- /* Scan each line and set variables */
- while (fgets (str, MAX_LEN, rc_file) != NULL) {
- if (lastch (str) != '\n') {
- /* ignore rest of file if line too long */
- fprintf (stderr, "\nParse error: line %d of configuration"
- " file too long.\n", l);
- fclose (rc_file);
- return -1; /* parse aborted */
- } else {
- lastch (str) = '\0';
- parse = parse_line (str, &var, &value); /* parse current line */
-
- switch (parse) {
- case LINE_BLANK: /* ignore blank lines and comments */
- case LINE_COMMENT:
- break;
- case LINE_OK:
- /* search table for matching config variable name */
- for (i = 0; i < VAR_COUNT && strcmp (vars[i].name, var); i++);
-
- if (i == VAR_COUNT) { /* no match */
- fprintf (stderr, "\nParse error: unknown variable "
- "at line %d of configuration file.\n", l);
- return -1; /* parse aborted */
- } else { /* variable found in table, set run time variables */
- switch (vars[i].type) {
- case VAL_INT:
- *((int *) vars[i].var) = atoi (value);
- break;
- case VAL_STR:
- if (!isquote (value[0]) || !isquote (lastch (value))
- || strlen (value) < 2) {
- fprintf (stderr, "\nParse error: string value "
- "expected at line %d of configuration "
- "file.\n", l);
- return -1; /* parse aborted */
- } else {
- /* remove the (") quotes */
- value++;
- lastch (value) = '\0';
- strcpy ((char *) vars[i].var, value);
- }
- break;
- case VAL_BOOL:
- if (!strcasecmp (value, "ON"))
- *((bool *) vars[i].var) = TRUE;
- else if (!strcasecmp (value, "OFF"))
- *((bool *) vars[i].var) = FALSE;
- else {
- fprintf (stderr, "\nParse error: boolean value "
- "expected at line %d of configuration "
- "file.\n", l);
- return -1; /* parse aborted */
- }
- break;
- case VAL_ATTR:
- if (str_to_attr (value, &fg, &bg, &hl) == -1) {
- fprintf (stderr, "\nParse error: attribute "
- "value expected at line %d of configuration "
- "file.\n", l);
- return -1; /* parse aborted */
- }
- ((int *) vars[i].var)[0] = fg;
- ((int *) vars[i].var)[1] = bg;
- ((int *) vars[i].var)[2] = hl;
- break;
- }
- }
- break;
- case LINE_ERROR:
- fprintf (stderr, "\nParse error: syntax error at line %d of "
- "configuration file.\n", l);
- return -1; /* parse aborted */
- }
- }
- l++; /* next line */
- }
-
- fclose (rc_file);
- return 0; /* parse successful */
- }
-
- /*
- * Convert an attribute to a string representation like this:
- *
- * "(foreground,background,highlight)"
- */
- static char *
- attr_to_str (int fg, int bg, int hl)
- {
- int i;
- static char str[MAX_LEN + 1];
-
- strcpy (str, "(");
- /* foreground */
- for (i = 0; fg != color_names[i].value; i++);
- strcat (str, color_names[i].name);
- strcat (str, ",");
-
- /* background */
- for (i = 0; bg != color_names[i].value; i++);
- strcat (str, color_names[i].name);
-
- /* highlight */
- strcat (str, hl ? ",ON)" : ",OFF)");
-
- return str;
- }
-
- /*
- * Extract the foreground, background and highlight values from an attribute
- * represented as a string in this form:
- *
- * "(foreground,background,highlight)"
- */
- static int
- str_to_attr (char *str, int *fg, int *bg, int *hl)
- {
- int i = 0, j, get_fg = 1;
- char tempstr[MAX_LEN + 1], *part;
-
- if (str[0] != '(' || lastch (str) != ')')
- return -1; /* invalid representation */
-
- /* remove the parenthesis */
- strcpy (tempstr, str + 1);
- lastch (tempstr) = '\0';
-
-
- /* get foreground and background */
-
- while (1) {
- /* skip white space before fg/bg string */
- while (whitespace (tempstr[i]) && tempstr[i] != '\0')
- i++;
- if (tempstr[i] == '\0')
- return -1; /* invalid representation */
- part = tempstr + i; /* set 'part' to start of fg/bg string */
-
- /* find end of fg/bg string */
- while (!whitespace (tempstr[i]) && tempstr[i] != ','
- && tempstr[i] != '\0')
- i++;
-
- if (tempstr[i] == '\0')
- return -1; /* invalid representation */
- else if (whitespace (tempstr[i])) { /* not yet ',' */
- tempstr[i++] = '\0';
-
- /* skip white space before ',' */
- while (whitespace (tempstr[i]) && tempstr[i] != '\0')
- i++;
-
- if (tempstr[i] != ',')
- return -1; /* invalid representation */
- }
- tempstr[i++] = '\0'; /* skip the ',' */
- for (j = 0; j < COLOR_COUNT && strcasecmp (part, color_names[j].name);
- j++);
- if (j == COLOR_COUNT) /* invalid color name */
- return -1;
- if (get_fg) {
- *fg = color_names[j].value;
- get_fg = 0; /* next we have to get the background */
- } else {
- *bg = color_names[j].value;
- break;
- }
- } /* got foreground and background */
-
-
- /* get highlight */
-
- /* skip white space before highlight string */
- while (whitespace (tempstr[i]) && tempstr[i] != '\0')
- i++;
- if (tempstr[i] == '\0')
- return -1; /* invalid representation */
- part = tempstr + i; /* set 'part' to start of highlight string */
-
- /* trim trailing white space from highlight string */
- i = strlen (part) - 1;
- while (whitespace (part[i]))
- i--;
- part[i + 1] = '\0';
-
- if (!strcasecmp (part, "ON"))
- *hl = TRUE;
- else if (!strcasecmp (part, "OFF"))
- *hl = FALSE;
- else
- return -1; /* invalid highlight value */
-
- return 0;
- }
-
-
- /*
- * Parse a line in the configuration file
- *
- * Each line is of the form: "variable = value". On exit, 'var' will contain
- * the variable name, and 'value' will contain the value string.
- *
- * Return values:
- *
- * LINE_BLANK - line is blank
- * LINE_COMMENT - line is comment
- * LINE_OK - line is ok
- * LINE_ERROR - syntax error in line
- */
- static int
- parse_line (char *line, char **var, char **value)
- {
- int i = 0;
-
- /* ignore white space at beginning of line */
- while (whitespace (line[i]) && line[i] != '\0')
- i++;
-
- if (line[i] == '\0') /* line is blank */
- return LINE_BLANK;
- else if (line[i] == '#') /* line is comment */
- return LINE_COMMENT;
- else if (line[i] == '=') /* variables names can't strart with a '=' */
- return LINE_ERROR;
-
- /* set 'var' to variable name */
- *var = line + i++; /* skip to next character */
-
- /* find end of variable name */
- while (!whitespace (line[i]) && line[i] != '=' && line[i] != '\0')
- i++;
-
- if (line[i] == '\0') /* syntax error */
- return LINE_ERROR;
- else if (line[i] == '=')
- line[i++] = '\0';
- else {
- line[i++] = '\0';
-
- /* skip white space before '=' */
- while (whitespace (line[i]) && line[i] != '\0')
- i++;
-
- if (line[i] != '=') /* syntax error */
- return LINE_ERROR;
- else
- i++; /* skip the '=' */
- }
-
- /* skip white space after '=' */
- while (whitespace (line[i]) && line[i] != '\0')
- i++;
-
- if (line[i] == '\0')
- return LINE_ERROR;
- else
- *value = line + i; /* set 'value' to value string */
-
- /* trim trailing white space from 'value' */
- i = strlen (*value) - 1;
- while (whitespace ((*value)[i]))
- i--;
- (*value)[i + 1] = '\0';
-
- return LINE_OK; /* no syntax error in line */
- }
-